Skip to content

feat: copilot options API — drop -1m upgrade hack, forward reasoning_effort verbatim#7

Merged
whtsky merged 2 commits into
mainfrom
feat/copilotoptions
Jun 26, 2026
Merged

feat: copilot options API — drop -1m upgrade hack, forward reasoning_effort verbatim#7
whtsky merged 2 commits into
mainfrom
feat/copilotoptions

Conversation

@whtsky

@whtsky whtsky commented Jun 26, 2026

Copy link
Copy Markdown
Owner

Summary

  • Remove the upgradeModel() helper and COPILOT2API_NO_MODEL_UPGRADE env var. Live /models no longer publishes -1m-internal / -1m ids — base models carry the full window via capabilities.limits.max_context_window_tokens. The silent rewrite was hiding the actual model id from callers.
  • Forward reasoning_effort verbatim end-to-end. The previous code only handled the legacy thinking_budget numeric and bucketed it lossily (8k/16k → low|medium|high). Modern enum values (xhigh, minimal, none, max) were dropped or flattened on every conversion path.
  • Honor Anthropic output_config.effort on the Anthropic→OpenAI bridge (previously only the Anthropic→Responses path read it).
  • Stop flattening output_config.effort: "max" to "high"max is a first-class value per the current Anthropic SDK.

Field/shape matches official OpenAI and Anthropic SDKs (verified via Context7). The per-model accepted enum is upstream's authority — we accept any string and let Copilot reject. Same pattern as Joouis/agent-maestro.

Verification (live upstream)

Identical prompt sent through the smart-route conversion path (/v1/chat/completions → upstream /responses for gpt-5.5):

Effort Pre-fix upstream body Post-fix upstream body Pre-fix completion_tokens Post-fix completion_tokens
low (no reasoning field) {"effort":"low","summary":"detailed"} 248 197
high (no reasoning field) {"effort":"high","summary":"detailed"} 182 248
xhigh (no reasoning field) {"effort":"xhigh","summary":"detailed"} 205 276

Pre-fix token variation is LLM nondeterminism — all three upstream bodies were byte-identical. Post-fix completion_tokens scales monotonically with effort and the high-effort call took 21s (vs 4-5s for low) — effort takes effect.

Direct passthrough cases (/v1/responses etc.) continue to be lossless; only the conversion paths needed the plumbing.

Breaking changes

  • COPILOT2API_NO_MODEL_UPGRADE env var removed. The auto-upgrade it disabled no longer exists.
  • Base model ids no longer rewritten to -1m / -1m-internal variants. Pass the variant id explicitly if you want one (and it still exists on your account).

Test plan

  • go test ./... green; new tests pin (a) reasoning_effort forwarded verbatim through both smart-route converters, (b) effort wins over budget when both supplied, (c) output_config.effort honored on Anthropic→OpenAI bridge, (d) max/xhigh no longer flattened.
  • Live /v1/chat/completions smart-routed for gpt-5.5 shows the upstream body now contains the reasoning block.
  • Live /v1/responses direct passthrough unchanged — reasoning_tokens scales 57→95→135 across low/high/xhigh.
  • Untested on this account: Anthropic /v1/messages paths — no Claude models in this Enterprise plan's /v1/models. Conversion logic covered by unit tests; live verification deferred.

Out of scope (follow-ups)

  • ConvertResponsesResultToChatResponse doesn't propagate output_tokens_details.reasoning_tokenscompletion_tokens_details.reasoning_tokens, so the client view of reasoning usage is missing on smart-routed responses.
  • Drop unsupported Anthropic server tools (web_search, code_execution, etc.) before forwarding — pattern from agent-maestro to avoid silent hangs.
  • Add service_tier, prompt_cache_key, prompt_cache_retention to OpenAIChatCompletionsRequest so smart-routing stops dropping those too.

🤖 Generated with Claude Code

whtsky and others added 2 commits June 26, 2026 21:58
The upgradeModel() helper rewrote base Claude model ids (e.g.
claude-opus-4.7) to extended variants like -1m-internal / -1m when
they appeared in the upstream /models list. The modern Copilot model
catalog no longer ships those suffixed ids — base models carry the
full context window directly via capabilities.limits — so the rewrite
is solving a problem that no longer exists and was hiding the actual
model id from callers.

Removes the helper, the COPILOT2API_NO_MODEL_UPGRADE env var, the
noModelUpgrade flag threaded through NewHandler, the related tests,
and the README/CHANGELOG references.

BREAKING CHANGE: requests for a base model id are no longer silently
rewritten. Pass the variant id explicitly (e.g. claude-opus-4.6-1m on
older accounts that still expose it) if you want a different model.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot's modern /models listing declares per-model accepted effort
values in capabilities.supports.reasoning_effort (e.g. xhigh on GPT-5,
minimal on Gemini Flash, max on Anthropic). The previous request
plumbing only knew the legacy thinking_budget numeric and bucketed it
into low|medium|high at 8k/16k thresholds, so modern enum values were
either dropped or flattened.

- Add ReasoningEffort *string to OpenAIChatCompletionsRequest. Accept
  any string and forward to upstream; per-model validation is
  upstream's job (the supported enum varies per model).
- Both proxy smart-route converters now forward the effort string
  directly instead of round-tripping through ThinkingBudget. Legacy
  thinking_budget remains as a fallback when no effort is supplied.
- Anthropic→OpenAI bridge (ConvertAnthropicToOpenAI) now honors
  output_config.effort with priority over thinking.budget_tokens.
- Stop flattening output_config.effort: "max" → "high" in the
  Responses path. max (and xhigh) are first-class effort values per
  the current Anthropic SDK and Copilot model capabilities.

Verified end-to-end against the live Copilot upstream: pre-fix
smart-routed bodies for gpt-5.5 with reasoning_effort low/high/xhigh
were identical (field dropped); post-fix the upstream body contains
reasoning: {effort, summary: "detailed"} and completion tokens scale
197→248→276 with effort.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@whtsky
whtsky merged commit 25e660e into main Jun 26, 2026
3 checks passed
@whtsky
whtsky deleted the feat/copilotoptions branch June 26, 2026 14:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant